package com.sihai.ehr.service.impl;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.management.RuntimeErrorException;

import com.sihai.ehr.model.sys.InviteFashionEnum;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Service;

import com.sihai.core.DataAccessor;
import com.sihai.core.DynamicQuery;
import com.sihai.core.Limit;
import com.sihai.core.LimitedList;
import com.sihai.core.QueryCreator;
import com.sihai.core.Sorter;
import com.sihai.core.support.HibernateDataAccessor;
import com.sihai.ehr.model.biz.InviteApply;
import com.sihai.ehr.model.biz.InviteApplyAuditing;
import com.sihai.ehr.model.biz.InviteArrange;
import com.sihai.ehr.model.biz.InviteFashion;
import com.sihai.ehr.model.sys.AuditStatus;
import com.sihai.ehr.model.sys.InviteEnum;
import com.sihai.ehr.model.sys.Organization;
import com.sihai.ehr.repository.AuditingRepository;
import com.sihai.ehr.service.InviteService;
import com.sihai.ehr.web.pojo.InviteApplyPojo;
import com.sihai.ehr.web.pojo.InviteArrangePojo;

/**
 * 招聘服务接口实现
 * 
 * @author Henry-PC
 */
@Service("inviteService")
public class InviteServiceImpl implements InviteService {

	@Resource
	private DataAccessor dataAccessor;

	@Resource
	private AuditingRepository auditingRepository;

	@Override
	public InviteApply getInviteApply(Long id) {
		if (id == null || id < 0) {
			throw new RuntimeException("【传入参数非法】");
		}
		try {
			return dataAccessor.get(InviteApply.class, id);
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：获取招聘申请单元对象数据库发生异常】【异常说明：+"
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.getInviteApply;参数id=" + id
					+ " 】");
		}

	}
	
	@Override
	public LimitedList<InviteApply> searchInviteAppliesByAuditStatus(Long organizationId, Long dutyId, AuditStatus auditStatus, Limit limit, Sorter sorter) {
		Organization organization = null;
		boolean isReadTopOrg = false;
		if (organizationId > 0) {
			try {
				organization = dataAccessor.get(Organization.class,
						organizationId);
				if (organization.getTopOrganization() == null) {
					isReadTopOrg = true;
				}
			} catch (Exception e) {
				return null;
			}
		}

		String strSQL = "from InviteApply i where i.cancel <> 1";
		try {
			if (auditStatus != null) {
				strSQL += " and i.auditStatus = '" + auditStatus.toString() + "'";
			}
			if (organizationId <= 0) {
				return dataAccessor.findByHql(InviteApply.class, strSQL, null,
						limit, sorter);
			} else if (dutyId <= 0) {
				return dataAccessor
						.findByHql(
								InviteApply.class,
								strSQL
										+ (isReadTopOrg ? " and (i.organization.topOrganization.id="
												+ organizationId
												+ " or i.organization.id=?)"
												: " and i.organization.id=?"),
								new Object[] { organizationId }, limit, sorter);
			} else {
				return dataAccessor
						.findByHql(
								InviteApply.class,
								strSQL
										+ (isReadTopOrg ? " and (i.organization.topOrganization.id="
												+ organizationId
												+ " or i.organization.id=?)"
												: " and i.organization.id=? ")
										+ " and duty.id=?", new Object[] {
										organizationId, dutyId }, limit, sorter);
			}
		} catch (Exception e) {
			throw new RuntimeErrorException(
					new Error(
							"【异常原因：根据组织关系及职务搜索招聘申请记录数据库发生异常】【发生地点：InviteServiceImpl.searchInviteApplies;参数organizationId="
									+ organizationId
									+ ",dutyId="
									+ dutyId
									+ "】"));
		}
	}

	@Override
	public LimitedList<InviteApply> searchInviteApplies(Long organizationId,
			Long dutyId, Limit limit, Sorter sorter) {
		try {
			return queryInviteApplies(organizationId, dutyId, null, limit,
					sorter);
		} catch (Exception e) {
			return null;
		}

	}

	@Override
	public LimitedList<InviteApply> searchInviteAppliesByNotPassAudit(
			Long organizationId, Long dutyId, Limit limit, Sorter sorter) {
		try {
			return queryInviteApplies(organizationId, dutyId,
					AuditStatus.reject_audit, limit, sorter);
		} catch (Exception e) {
			return null;
		}

	}
	
	@Override
	public LimitedList<InviteApply> searchInviteAppliesByPassAudit(
			Long organizationId, Long dutyId, Limit limit, Sorter sorter) {
		try {
			return queryInviteApplies(organizationId, dutyId,
					AuditStatus.pass_audit, limit, sorter);
		} catch (Exception e) {
			return null;
		}

	}

	/**
	 * 根据组织，职务，审核结果查询招聘申请
	 * 
	 * @param organizationId
	 * @param dutyId
	 * @param auditStatus
	 * @param limit
	 * @param sorter
	 * @return
	 */
	private LimitedList<InviteApply> queryInviteApplies(Long organizationId,
			Long dutyId, AuditStatus auditStatus, Limit limit, Sorter sorter) {
		Organization organization = null;
		boolean isReadTopOrg = false;
		if (organizationId > 0) {
			try {
				organization = dataAccessor.get(Organization.class,
						organizationId);
				if (organization.getTopOrganization() == null) {
					isReadTopOrg = true;
				}
			} catch (Exception e) {
				return null;
			}
		}

		String strSQL = "from InviteApply i where i.cancel <> 1";
		try {
			if (auditStatus != null) {
				if(auditStatus == AuditStatus.pass_audit){
					strSQL += " and i.auditStatus='" + auditStatus.toString() + "'";
				}else{
					strSQL += " and i.auditStatus != '" + AuditStatus.pass_audit.toString() + "'";
				}
			}
			if (organizationId <= 0) {
				return dataAccessor.findByHql(InviteApply.class, strSQL, null,
						limit, sorter);
			} else if (dutyId <= 0) {
				return dataAccessor
						.findByHql(
								InviteApply.class,
								strSQL
										+ (isReadTopOrg ? " and (i.organization.topOrganization.id="
												+ organizationId
												+ " or i.organization.id=?)"
												: " and i.organization.id=?"),
								new Object[] { organizationId }, limit, sorter);
			} else {
				return dataAccessor
						.findByHql(
								InviteApply.class,
								strSQL
										+ (isReadTopOrg ? " and (i.organization.topOrganization.id="
												+ organizationId
												+ " or i.organization.id=?)"
												: " and i.organization.id=? ")
										+ " and duty.id=?", new Object[] {
										organizationId, dutyId }, limit, sorter);
			}
		} catch (Exception e) {
			throw new RuntimeErrorException(
					new Error(
							"【异常原因：根据组织关系及职务搜索招聘申请记录数据库发生异常】【发生地点：InviteServiceImpl.searchInviteApplies;参数organizationId="
									+ organizationId
									+ ",dutyId="
									+ dutyId
									+ "】"));
		}
	}

	@Override
	public LimitedList<InviteApplyPojo> searchInviteAppliesTOPOJO(
			Long organizationId, Long dutyId, Limit limit, Sorter sorter) {
		String hql = "select new com.sihai.ehr.web.pojo.InviteApplyPojo(i.id,id.organization.fullName,i.duty.dutyName) from InviteApply i where i.cancel <> 1";
		try {
			if (organizationId <= 0) {
				return dataAccessor.findByHql(InviteApplyPojo.class, hql, null,
						limit, sorter);
			} else if (dutyId <= 0) {
				return dataAccessor.findByHql(InviteApplyPojo.class, hql
						+ " and i.organization.id=?",
						new Object[] { organizationId }, limit, sorter);
			} else {
				return dataAccessor.findByHql(InviteApplyPojo.class, hql
						+ " and i.organization.id=? and duty.id=?",
						new Object[] { organizationId, dutyId }, limit, sorter);
			}
		} catch (Exception e) {
			throw new RuntimeException(
					"【异常原因：根据组织关系及职务搜索招聘申请记录数据库发生异常】【发生地点：InviteServiceImpl.searchInviteAppliesTOPOJO;参数organizationId="
							+ organizationId + ",dutyId=" + dutyId + "】");
		}
	}

	@Override
	public LimitedList<InviteApply> searchInviteApplies(
			final InviteApply inviteApply, Limit limit, Sorter sorter) {
		if (inviteApply == null) {
			try {
				return dataAccessor.findByClass(InviteApply.class, limit,
						sorter);
			} catch (Exception e) {
				throw new RuntimeException(
						"【异常原因：根据组织关系及职务搜索招聘申请记录数据库发生异常】【发生地点：InviteServiceImpl.searchInviteApplies;参数inviteApply为空】");
			}
		}
		return dataAccessor.findByQuery(InviteApply.class, new QueryCreator() {

			@Override
			public Query createQuery(Session session) {
				DynamicQuery dynamicQuery = new DynamicQuery(
						"from InviteApply i where i.cancel <> 1");
				dynamicQuery.appendIfNotNull(
						"and i.organization.id =:organization_id",
						"organization_id", inviteApply.getOrganization()
								.getId());
				dynamicQuery.appendIfNotNull("and i.duty.id =:duty_id",
						"duty_id", inviteApply.getDuty().getId());
				return dynamicQuery.build(session);
			}
		}, limit, sorter);
	}

	@Override
	public void saveInviteApply(InviteApply inviteApply) {
		if (inviteApply == null) {
			throw new RuntimeException("【inviteApply对象参数异常】");
		}
		boolean isNew = inviteApply.getId() != null && inviteApply.getId() > 0 ? false
				: true;
		try {
			dataAccessor.saveOrUpdate(inviteApply);
			// 添加审核信息
			if (isNew) {
				saveInviteApplyAuditings(inviteApply, 1);
			}

		} catch (Exception e) {
			throw new RuntimeException("【异常原因：保存招聘申请数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.saveInviteApply】");
		}
	}

	/**
	 * 创建审核流程
	 * 
	 * @param inviteApply
	 * @param auditNo
	 */
	public void saveInviteApplyAuditingProcess(InviteApply inviteApply,
			int auditNo) {
		try {
			auditingRepository.saveAuditingProcess(inviteApply, auditNo);
		} catch (Exception ex) {
			//
		}
	}

	// 创建审核流程
	private void saveInviteApplyAuditings(InviteApply inviteApply, int auditNo) {
		auditingRepository.saveAuditingProcess(inviteApply, auditNo);
	}

	@Override
	public void removeInviteApplys(final String inviteApplyIds) {
		if (inviteApplyIds == null || inviteApplyIds.isEmpty()) {
			throw new RuntimeException("【参数异常：employeebaseinfoIds为空】");
		}
		try {
			dataAccessor.batchUpdate(new QueryCreator() {

				@Override
				public Query createQuery(Session session) {
					return session.createQuery(MessageFormat
							.format("update InviteApply i set i.cancel = 1 where id in ({0})",
									inviteApplyIds));
				}
			});
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：移出招聘申请数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.removeInviteApplys】");
		}
	}

	@Override
	public InviteApplyAuditing getInviteApplyAuditing(Long id) {
		if (id <= 0) {
			return null;
		}
		try {
			return dataAccessor.get(InviteApplyAuditing.class, id);
		} catch (Exception e) {
			e.printStackTrace(); // To change body of catch statement use File |
			// Settings | File Templates.
		}
		return null;
	}

	@Override
	public List<List<InviteApplyAuditing>> searchApplyAuditings(
			Long inviteApplyId, Limit limit, Sorter sorter) {
		return auditingRepository.findByHql(InviteApplyAuditing.class,
				"from InviteApplyAuditing i where i.inviteApply.id = ?",
				new Object[] { inviteApplyId });
	}

	@Override
	public LimitedList<InviteApplyAuditing> searchApplyAuditings(
			InviteApplyAuditing inviteApplyAuditing, Limit limit, Sorter sorter) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void saveInviteApplyAuditing(InviteApplyAuditing inviteApplyAuditing) {
		if (inviteApplyAuditing == null) {
			throw new RuntimeException("【inviteApplyAuditing对象参数异常】");
		}
		try {
			dataAccessor.saveOrUpdate(inviteApplyAuditing);
			InviteApply inviteApply = inviteApplyAuditing.getInviteApply();

			boolean isReject = inviteApplyAuditing.getStatus() == AuditStatus.reject_audit;
			inviteApply.setAuditStatus(isReject ? AuditStatus.wait_audit
					: inviteApplyAuditing.getStatus());

			// 如果未通过审核,则再创建一个审核流程
			if (isReject) {
				saveInviteApplyAuditings(inviteApply,
						inviteApplyAuditing.getAuditNo() + 1);
			}
			dataAccessor.save(inviteApply);
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：保存招聘审核结果到数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.saveInviteApplyAuditing】");
		}
	}

	@Override
	public void removeInviteApplyAuditings(String inviteApplyAuditings) {
		// TODO Auto-generated method stub

	}

	@Override
	public InviteArrange getInviteArrange(Long id) {
		if (id <= 0) {
			throw new RuntimeException("［参数异常，ID为空］");
		}
		try {
			return dataAccessor.get(InviteArrange.class, id);
		} catch (Exception e) {
			e.printStackTrace(); // To change body of catch statement use File |
			// Settings | File Templates.
		}
		return null;
	}

	/**
	 * 根据招聘申请编号获取招聘安排
	 */
	public InviteArrange getInviteArrangeByApplyId(final Long inviteId) {
		if (inviteId <= 0) {
			throw new RuntimeException("［参数异常，inviteId为空］");
		}
		List<InviteArrange> mArranges = dataAccessor.findByQuery(
				InviteArrange.class, new QueryCreator() {

					@Override
					public Query createQuery(Session session) {
						DynamicQuery dynamicQuery = new DynamicQuery(
								"from InviteArrange i where i.cancel <> 1");
						dynamicQuery.appendIfNotNull(
								"and i.inviteApply.id =:invite_id",
								"invite_id", inviteId);
						return dynamicQuery.build(session);
					}
				}, null, null);
		if (mArranges != null && mArranges.size() > 0) {
			return mArranges.get(0);
		} else {
			return null;
		}
	}

	@Override
	public LimitedList<InviteArrangePojo> searchInviteArranges(
			Long organizationId, Long dutyId, InviteEnum inviteEnum,
			Limit limit, Sorter sorter) {
		LimitedList<InviteArrangePojo> inviteArrangePojos = new LimitedList<InviteArrangePojo>();
		Organization organization = null;
		boolean isReadTopOrg = false;
		if (organizationId > 0) {
			try {
				organization = dataAccessor.get(Organization.class,
						organizationId);
				if (organization.getTopOrganization() == null) {
					isReadTopOrg = true;
				}
			} catch (Exception e) {
				return null;
			}
		}
		try {
			String strSQL = "select a.id as id,i.id as invite_id,d.duty_name,o.id as org_id,a.channel,i.apply_amount,a.complete_num,a.invite_result "
					+ "from invite_arrange a right outer join invite_apply i on a.invite_apply_id=i.id, "
					+ "duty d cross join organization o "
					+ "where i.duty_id=d.id and i.organization_id=o.id and i.cancel <> 1 and i.audit_status='"
					+ AuditStatus.pass_audit.toString() + "' ";
			if (inviteEnum != null) {
				if (inviteEnum != InviteEnum.not_scheduled) {
					strSQL += " and a.invite_result='" + inviteEnum.toString()
							+ "'";
				} else {
					strSQL += " and a.invite_result is null";
				}
			}

			if (organizationId < 0) {
				return dataAccessor.findByHql(InviteArrangePojo.class, strSQL,
						null, limit, sorter);
			} else if (dutyId < 0) {
				strSQL += (isReadTopOrg ? " and (o.top_organization_id="
						+ organizationId + " or i.organization_id="
						+ organizationId + ")" : "and i.organization_id="
						+ organizationId);
			} else {
				strSQL += (isReadTopOrg ? " and (o.top_organization_id="
						+ organizationId + " or i.organization_id="
						+ organizationId + ")" : "and i.organization_id="
						+ organizationId)
						+ "and i.duty_id=" + dutyId;
			}

			strSQL += "  limit " + limit.getOffset() + "," + limit.getCount();
			Session vSession = ((HibernateDataAccessor) dataAccessor)
					.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Connection vConnection = vSession.connection();
			Statement vStatement = vConnection.createStatement();
			ResultSet rs = vStatement.executeQuery(strSQL);

			while (rs.next()) {
				InviteArrangePojo pojo = new InviteArrangePojo();
				pojo.setId(rs.getLong("id"));
				pojo.setInviteId(rs.getLong("invite_id"));
				pojo.setDutyName(rs.getString("duty_name"));
				pojo.setOrgId(rs.getLong("org_id"));
				pojo.setChannel(rs.getString("channel") == null ? ""
						: InviteFashionEnum.valueOf(rs.getString("channel"))
								.getName());
				pojo.setApplyAmount(rs.getInt("apply_amount"));
				pojo.setCompleteNum(rs.getInt("complete_num"));
				pojo.setInviteResult(rs.getString("invite_result") == null ? InviteEnum.not_scheduled
						: InviteEnum.valueOf(rs.getString("invite_result")));
				inviteArrangePojos.add(pojo);
			}
			rs.close();
            vStatement.close();
            vConnection.close();
			return inviteArrangePojos;
		} catch (Exception e) {
			throw new RuntimeException(
					"【异常原因：根据组织关系及职务搜索招聘申请记录数据库发生异常】【异常原因："
							+ e.getMessage()
							+ "】【发生地点：InviteServiceImpl.searchInviteApplies;参数organizationId="
							+ organizationId + ",dutyId=" + dutyId + "】");
		}
	}

	@Override
	public LimitedList<InviteArrange> searchInviteArranges(
			final InviteArrange inviteArrange, Limit limit, Sorter sorter) {
		if (inviteArrange == null) {
			try {
				return dataAccessor.findByClass(InviteArrange.class, limit,
						sorter);
			} catch (Exception e) {
				throw new RuntimeException(
						"【异常原因：根据组织关系及职务搜索招聘安排记录数据库发生异常】【发生地点：InviteServiceImpl.searchInviteArranges;参数inviteArrange为空】");
			}
		}
		return dataAccessor.findByQuery(InviteArrange.class,
				new QueryCreator() {

					@Override
					public Query createQuery(Session session) {
						DynamicQuery dynamicQuery = new DynamicQuery(
								"from InviteArrange i where i.cancel <> 1");
						dynamicQuery.appendIfNotNull(
								"and i.inviteApply.id =:inviteapply_id",
								"inviteapply_id",
								inviteArrange.getInviteApply() != null ? inviteArrange
										.getInviteApply().getId() : null);
						dynamicQuery.appendIfNotNull(
								"and i.inviteResult =:inviteResult",
								"inviteResult",
								inviteArrange.getInviteResult() != null ? inviteArrange
										.getInviteResult().toString() : null);
						return dynamicQuery.build(session);
					}
				}, limit, sorter);
	}

	@Override
	public void saveInviteArrange(InviteArrange inviteArrange) {
		if (inviteArrange == null) {
			throw new RuntimeException("【inviteArrange对象参数异常】");
		}
		try {
			dataAccessor.saveOrUpdate(inviteArrange);
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：保存招聘安排数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.saveInviteArrange】");
		}
	}

	@Override
	public void removeInviteArranges(final String inviteArrangeIds) {
		if (inviteArrangeIds == null || inviteArrangeIds.isEmpty()) {
			throw new RuntimeException("【参数异常：inviteArrangeIds为空】");
		}
		try {
			dataAccessor.batchUpdate(new QueryCreator() {

				@Override
				public Query createQuery(Session session) {
					return session.createQuery(MessageFormat
							.format("update InviteArrange i set i.cancel = 1 where id in ({0})",
									inviteArrangeIds));
				}
			});
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：移出招聘申请数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.removeInviteArranges】");
		}
	}

	@Override
	public InviteFashion getInviteFashion(Long id) {
		if (id == null || id < 0) {
			throw new RuntimeException("【传入参数非法】");
		}
		try {
			return dataAccessor.get(InviteFashion.class, id);
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：获取招聘渠道单元对象数据库发生异常】【异常说明：+"
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.getInviteFashion;参数id=" + id
					+ " 】");
		}
	}

	@Override
	public LimitedList<InviteFashion> searchFashions(String hql, Limit limit,
			Sorter sorter) {
		try {
			if (hql == null || hql.isEmpty()) {
				return dataAccessor.findByHql(InviteFashion.class,
						"from InviteFashion i where 1=1 ", null, limit, sorter);
			} else {
				return dataAccessor.findByHql(InviteFashion.class,
						"from InviteFashion i where 1=1 " + hql, null, limit,
						sorter);
			}
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：根据HQL指定条件语句查询渠道列表数据库发生异常】【异常说明：+"
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.searchFashions;参数hql=" + hql
					+ " 】");
		}

	}

	@Override
	public LimitedList<InviteFashion> searchFashions(
			final InviteFashion inviteFashion, Limit limit, Sorter sorter) {
		if (inviteFashion == null) {
			try {
				return dataAccessor.findByClass(InviteFashion.class, limit,
						sorter);
			} catch (Exception e) {
				throw new RuntimeException(
						"【异常原因：搜索招聘渠道列表数据库发生异常】【发生地点：InviteServiceImpl.searchFashions;参数inviteFashion为空】");
			}
		}
		return dataAccessor.findByQuery(InviteFashion.class,
				new QueryCreator() {
					@Override
					public Query createQuery(Session session) {
						DynamicQuery dynamicQuery = new DynamicQuery(
								"from InviteFashion i where 1=1");
						dynamicQuery.appendIfNotNull("and i.chancel =:chancel",
								"chancel", inviteFashion.getChannel());
						return dynamicQuery.build(session);
					}
				}, limit, sorter);
	}

	@Override
	public void saveInviteFashion(InviteFashion inviteFashion) {
		if (inviteFashion == null) {
			throw new RuntimeException("【inviteFashion对象参数异常】");
		}
		try {
			dataAccessor.saveOrUpdate(inviteFashion);
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：保存招聘渠道数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.saveInviteFashion】");
		}
	}

	@Override
	public void removeInviteFashions(final String inviteFashionIds) {
		if (inviteFashionIds == null || inviteFashionIds.isEmpty()) {
			throw new RuntimeException("【参数异常：inviteFashionIds为空】");
		}
		try {
			dataAccessor.batchUpdate(new QueryCreator() {

				@Override
				public Query createQuery(Session session) {
					return session.createQuery(MessageFormat.format(
							"delete from InviteFashion i where id in ({0})",
							inviteFashionIds));
				}
			});
		} catch (Exception e) {
			throw new RuntimeException("【异常原因：移出招聘渠道数据库发生异常】【异常说明："
					+ e.getMessage()
					+ "】【发生地点：InviteServiceImpl.removeInviteFashions】");
		}
	}

}
